package com.kk.utils;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author kl
 * @version 1.0
 * @description: IP工具类
 * @date 2025/10/17 下午2:47
 */
@Slf4j
public class IpUtils {
    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST_IP = "127.0.0.1";
    private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
    private static final int IP_LENGTH = 15;

    /**
     * 获取客户端的ip
     */
    public static String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            return UNKNOWN;
        }
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (LOCALHOST_IP.equals(ip) || LOCALHOST_IPV6.equals(ip)) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    log.error("获取IP地址失败", e);
                }
                if (inet != null) {
                    ip = inet.getHostAddress();
                }
            }
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP，多个IP按照','分割
        if (ip != null && ip.length() > IP_LENGTH) {
            int index = ip.indexOf(",");
            if (index > 0) {
                ip = ip.substring(0, index);
            }
        }
        return LOCALHOST_IPV6.equals(ip) ? LOCALHOST_IP : ip;
    }

    /**
     * 获取当前请求的IP地址
     */
    public static String getIpAddr() {
        HttpServletRequest request = getRequest();
        return getIpAddr(request);
    }

    public static HttpServletRequest getRequest() {
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes != null ? attributes.getRequest() : null;
    }

    /**
     * 获取当前请求的操作系统
     */
    public static String getOs() {
        HttpServletRequest request = getRequest();
        return getOs(request);
    }

    /**
     * 获取操作系统
     */
    public static String getOs(HttpServletRequest request) {
        if (request == null) {
            return UNKNOWN;
        }
        String userAgentStr = request.getHeader("User-Agent");
        if (!StringUtils.hasText(userAgentStr)) {
            return UNKNOWN;
        }
        return parseOs(userAgentStr);
    }

    /**
     * 获取浏览器类型
     */
    public static String getBrowser(HttpServletRequest request) {
        if (request == null) {
            return UNKNOWN;
        }
        String userAgentStr = request.getHeader("User-Agent");
        if (!StringUtils.hasText(userAgentStr)) {
            return UNKNOWN;
        }
        return parseBrowser(userAgentStr);
    }

    /**
     * 解析操作系统
     */
    private static String parseOs(String userAgent) {
        if (userAgent == null) {
            return UNKNOWN;
        }
        userAgent = userAgent.toLowerCase();

        if (userAgent.contains("windows nt 10.0")) {
            return "Windows 10";
        } else if (userAgent.contains("windows nt 6.3")) {
            return "Windows 8.1";
        } else if (userAgent.contains("windows nt 6.2")) {
            return "Windows 8";
        } else if (userAgent.contains("windows nt 6.1")) {
            return "Windows 7";
        } else if (userAgent.contains("windows nt 6.0")) {
            return "Windows Vista";
        } else if (userAgent.contains("windows nt 5.2")) {
            return "Windows Server 2003";
        } else if (userAgent.contains("windows nt 5.1") || userAgent.contains("windows xp")) {
            return "Windows XP";
        } else if (userAgent.contains("windows")) {
            return "Windows";
        } else if (userAgent.contains("mac os x")) {
            Pattern pattern = Pattern.compile("mac os x ([\\d._]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "Mac OS X " + matcher.group(1).replace("_", ".");
            }
            return "Mac OS X";
        } else if (userAgent.contains("macintosh")) {
            return "Mac OS";
        } else if (userAgent.contains("android")) {
            Pattern pattern = Pattern.compile("android ([\\d.]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "Android " + matcher.group(1);
            }
            return "Android";
        } else if (userAgent.contains("iphone") || userAgent.contains("ipad")) {
            Pattern pattern = Pattern.compile("os ([\\d_]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "iOS " + matcher.group(1).replace("_", ".");
            }
            return "iOS";
        } else if (userAgent.contains("linux")) {
            return "Linux";
        } else if (userAgent.contains("ubuntu")) {
            return "Ubuntu";
        } else if (userAgent.contains("unix")) {
            return "Unix";
        }

        return UNKNOWN;
    }

    /**
     * 解析浏览器
     */
    private static String parseBrowser(String userAgent) {
        if (userAgent == null) {
            return UNKNOWN;
        }

        // Edge浏览器
        if (userAgent.contains("Edg/")) {
            Pattern pattern = Pattern.compile("Edg/([\\d.]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "Edge " + matcher.group(1);
            }
            return "Edge";
        }

        // Chrome浏览器
        if (userAgent.contains("Chrome/")) {
            Pattern pattern = Pattern.compile("Chrome/([\\d.]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "Chrome " + matcher.group(1);
            }
            return "Chrome";
        }

        // Firefox浏览器
        if (userAgent.contains("Firefox/")) {
            Pattern pattern = Pattern.compile("Firefox/([\\d.]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "Firefox " + matcher.group(1);
            }
            return "Firefox";
        }

        // Safari浏览器
        if (userAgent.contains("Safari/") && !userAgent.contains("Chrome")) {
            Pattern pattern = Pattern.compile("Version/([\\d.]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "Safari " + matcher.group(1);
            }
            return "Safari";
        }

        // Opera浏览器
        if (userAgent.contains("OPR/")) {
            Pattern pattern = Pattern.compile("OPR/([\\d.]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "Opera " + matcher.group(1);
            }
            return "Opera";
        }

        // IE浏览器
        if (userAgent.contains("MSIE") || userAgent.contains("Trident/")) {
            Pattern pattern = Pattern.compile("MSIE ([\\d.]+)");
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "IE " + matcher.group(1);
            }
            pattern = Pattern.compile("rv:([\\d.]+)");
            matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                return "IE " + matcher.group(1);
            }
            return "IE";
        }

        return UNKNOWN;
    }
    /**
     * 根据IP地址获取地理位置
     * 这里使用简单的本地/局域网判断，生产环境建议接入IP库（如高德、百度等）
     */
    public static String getLocationByIp(String ip) {
        if (!StringUtils.hasText(ip)) {
            return "未知";
        }
        if (LOCALHOST_IP.equals(ip) || "localhost".equals(ip)) {
            return "本地";
        }
        if (ip.startsWith("192.168.") || ip.startsWith("10.") || ip.startsWith("172.")) {
            return "局域网";
        }

        // TODO: 接入真实的IP定位服务
        // 可以使用：高德地图API、百度地图API、淘宝IP库、ip2region等
        // 示例：使用ip2region离线库
        // try {
        //     DbSearcher searcher = new DbSearcher(config, dbPath);
        //     DataBlock dataBlock = searcher.btreeSearch(ip);
        //     return dataBlock.getRegion();
        // } catch (Exception e) {
        //     log.error("IP定位失败", e);
        // }

        return "未知";
    }
}